/*
 * Cubem - Copyright (C) 2008 Ewan Davies
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 *
 */
package cubem;

import java.io.*;

/**
 *
 * @author Ewan
 */
public class Solve {

    public Solve(String solveScramble, long solveTime, int solvePenalties) {
        scramble = solveScramble;
        time = solveTime;
        penalties = solvePenalties;
    }
   public Solve(byte[] data) {
       ByteArrayInputStream bs = new ByteArrayInputStream(data);
       DataInputStream ds = new DataInputStream(bs);
       try {
        scramble = ds.readUTF();
        time = ds.readLong();
        penalties = ds.readInt(); 
        ds.close();
        bs.close();
       } catch (Exception e) {
        scramble = "";
        time = 0;
        penalties = 0;
       }
    }
    
    String scramble;
    long time;
    int penalties;
    
    /**
     * Returns the time the solve took
     * @return the solve time
     * TODO: should the raw time be outputted?
     */
    public long getTime() {
        switch (penalties) {
            case PEN_POP:
                return time;
            case PEN_DNF:
                return Long.MAX_VALUE;//PEN_DNF;
            case PEN_FOUL:
                return time + PEN_FOUL_TIME;
            default:
                return time;
        }
    }
    
    public long getRawTime() {
        return time;
    }
    
    public String getTimeString() {
        switch (penalties) {
            case PEN_POP:
                return "Pop " + convertToTimeString(getTime());
            case PEN_DNF:
                return "DNF";
            case PEN_FOUL:
                return convertToTimeString(getTime()) + " (incl. +" + (int)(PEN_FOUL_TIME / 1000) + ")";
            default:
                return convertToTimeString(getTime());
        }
    }
    
    public String getScramble() {
        return scramble;
    }
    
    public int getPenalties() {
        return penalties;
    }
    
    public byte[] serialize() throws IOException {
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        ByteArrayOutputStream bs2 = new ByteArrayOutputStream();
        DataOutputStream ds = new DataOutputStream(bs);

        ds.writeUTF(scramble);
        ds.writeLong(time);
        ds.writeInt(penalties);
        
        byte[] output = bs.toByteArray();
        ds.close();
        bs.close();
        return output;
    }
    
    public static final int PEN_NONE = 0;
    public static final int PEN_POP = -1;
    public static final int PEN_DNF = -2;
    public static final int PEN_FOUL = -3;
    
    public static final long PEN_FOUL_TIME = 2000;
    public static final int SOLVE_DATA_LENGTH = 244;
    
    /**
     * Gets a string representation of the length of time beween two system times
     * @param start the start time
     * @param end the end time
     * @return the string representing the elapsed time
     */
    public static String convertToTimeString(long start, long end) {
        return convertToTimeString(end - start);
    }
    
    public static final String convertToTimeString(long elapsed) {
       String timeString = "";
    
       if (elapsed == 0) 
           return "";
       if (elapsed < 0) {
            elapsed = -elapsed;
            timeString = "-";
        }
       
       int mils = (int) (elapsed % 1000);
       elapsed /= 1000;
       int sec = (int) (elapsed % 60);
       elapsed /= 60;
       int min = (int) (elapsed % 60);
       elapsed /= 60;
/*     int hours = (int) elapsed;
       
       if (hours < 10) {
           timeString += "0";
       }
       timeString += hours;
       timeString += ':'; */
       if (min < 10) {
           timeString += '0';
       }
       timeString += min;
       timeString += ':';
       if (sec < 10) {
           timeString += '0';
       }
       timeString += sec;
       timeString += '.';
              
       /* convert mils to hundreths */
       int rdown = mils / 10;
       int rup = rdown + 1;
       if (Math.abs((rup*10) - mils) <= Math.abs(mils - (rdown*10)))
           mils = rup;
       else
           mils = rdown;
       
       if (mils < 10) {
           timeString += '0';
       }
       timeString += mils;
       
       return timeString; 
    }
}
